

#include <stdint.h>
#include <stddef.h>
#include <stdio.h>

#include "dbg_cli.h"


static uint32_t  esc_value = 0;

static int proc_esc_sequences( uint8_t tch, uint32_t * pcd )
{
	uint32_t  temp = tch;

	/**/
	if ( esc_value == 0 )
	{
		if ( temp == 0x1b )
		{
			esc_value = 0x1b;
			return 1;
		}
		
		goto  try_post;
	}
	else if ( esc_value == 0x1b )
	{
		if ( temp == 0x5b )
		{
			esc_value = 0x1b5b;
			return 2;
		}
		else
		{
			/* error code? */
			esc_value = 0;
			return 3;
		}
	}
	else if ( esc_value == 0x1b5b )
	{
		temp = 0x5b00 | temp;
		esc_value = 0;
		goto try_post;
	}
	else
	{
		/* error code? */
		esc_value = 0;
		return 4;
	}
	
	
	/**/
try_post:
	*pcd = temp;
	return 0;
}



#define  LINE_LEN    80
static int  sidx = 0;
static char  spad[LINE_LEN + 1];

static void  proc_ucode( uint32_t temp )
{
	switch ( temp )
	{
		case  0x5b41:		/* up arrow */
		case  0x5b42:	    /* down arrow */
			break;
			
		case 0x7f:
		case 0x08:
			/* back space */
			if ( sidx > 0 )
			{
				sidx--;			
				printf( "\b \b" );
			}
			break;

		case 0x03:
			/* ctrl + c : ??????. */
			break;

		case 0x0A:
		case 0x0D:
			/* enter */
			if ( sidx <= 0 )
			{
				printf( "\n>" );
				break;
			}
			
			spad[sidx] = '\0';
			printf( "\n" );
			debug_proc_line( spad );
			sidx = 0;
			printf( "\n>" );
			break;

		default:
			if ( temp > 0x7F )
			{
				/* nothing proc */
				break;
			}
			
			printf( "%c", (int)temp );
		
			if ( sidx < LINE_LEN )
			{
				spad[sidx] = (char)temp;
				sidx += 1;
			}
			else
			{
				sidx = 0;
				printf( "\n\t:: too long, try again\n" );
				printf( "\n>" );
			}
			break;

	}
	
	return;
}




static inline uint32_t  read_reg( uintptr_t addr )
{
   return (*((volatile uint32_t *) (addr)));
}


static inline void  write_reg( uintptr_t addr, uint32_t value )
{
  *(volatile uint32_t *)(addr) = value;
  return;
}


#define UART_DR		   0x00
#define UART_FR		   0x18


void  con_proc_input( void )
{
	int  iret;
	uintptr_t  pbase = 0x40034000;
	uint32_t  temp;

	while( 1 )
	{
		temp = read_reg( pbase + UART_FR );
		if ( (temp & 0x10) != 0 )
		{
			continue;
		}

		iret = proc_esc_sequences( (uint8_t)read_reg(pbase + UART_DR ), &temp );
		if ( iret == 0 )
		{
			proc_ucode( temp );
		}
	}

	/**/
	return;
}


